# coding=utf-8

from collections import defaultdict
from copy import deepcopy
import datetime
import json
import re
import time
import shlex

from django.db import connection
from django.http import HttpResponse, JsonResponse

from lib.common import AbstractHandler, escape_string
from project.settings import USER_TYPE
from services.datamodel.lesson.models import Lesson, mm_Lesson


class BaseHandler(AbstractHandler):
    # These enviroment values are for tags
    SGT_INT_VALUE_TAGS = ['gradeid', 'subjectid', 'textbookverid', 'textbookvolid', 'textbookid']

    def __init__(self, app_logger):

        AbstractHandler.__init__(self,app_logger)

        self.CACHE_KEY_FMT = 'lssn_'

    def handle_search_base(self, request,author_limit=None):
        self.app_logger.debug("handle_search")

        for require_param in ['subjectid', 'firstid', 'lastid', 'direction']:
            if require_param not in request.GET:
                return JsonResponse(
                    {'retcode': 1,
                     'msg': '需要参数`{}`'.format(require_param)})

        firstid = request.GET['firstid']
        lastid = request.GET['lastid']
        direction = request.GET['direction']
        subjectid = request.GET['subjectid']
        needsgt = 1 if 'needsgt' in request.GET else None

        if not subjectid.isdigit():
            return JsonResponse(
                {'retcode': 1, 'msg': '参数`subjectid`错误'})

        # TODO to see if there is a better way to avoid to use
        # Lessons._meta.db_table, which is a protected method
        where_clause = ' %s.subjectid = %s' % (Lesson._meta.db_table, subjectid)

        orderby = 'DESC' if direction == 'ASC' else 'ASC'
        if firstid == lastid and (firstid == -1 or firstid == '-1'):
            pass
        else:
            if direction == 'ASC':
                if lastid == '0':
                    pass
                else:
                    where_clause += ' AND %s.id < %s' % (Lesson._meta.db_table, lastid)
            elif direction == 'DESC':
                where_clause += ' AND %s.id > %s' % (Lesson._meta.db_table, firstid)
            else:
                return JsonResponse(
                    {'retcode': 1, 'msg': '参数`direction`值未知'})

        if author_limit:
            limitClause = []
            for oneLimit in author_limit:
                limitClause.append('(%s.authortype=%s and %s.authorid=%s)'% (Lesson._meta.db_table,
                                                                         oneLimit[0],
                                                                         Lesson._meta.db_table,
                                                                         oneLimit[1]))
            limitClauseStr = ' or '.join(limitClause)
            where_clause += ' AND ( ' + limitClauseStr + ' )'

        if 'createtimebefore' in request.GET:
            createtime_string = time.strftime(
                "%Y-%m-%d %H:%M:%S", time.gmtime(
                    float(request.GET['createtimebefore'])))
            limitClauseStr = '%s.create_time<="%s"' % (
                Lesson._meta.db_table, createtime_string)
            where_clause += ' AND ( ' + limitClauseStr + ' )'

        if 'createtimeafter' in request.GET:
            createtime_string = time.strftime(
                "%Y-%m-%d %H:%M:%S", time.gmtime(
                    float(request.GET['createtimeafter'])))
            limitClauseStr = '%s.create_time>="%s"' % (
                Lesson._meta.db_table, createtime_string)
            where_clause += ' AND ( ' + limitClauseStr + ' )'

        if 'searchkeyword' in request.GET:
            filterList = []
            kwStr = request.GET['searchkeyword']
            kwList = [s for s in shlex.split(escape_string(kwStr))]

            for kw in kwList:
                if kw:
                    filterList.append(
                        "%s.name LIKE BINARY '%%%s%%' " % (
                            Lesson._meta.db_table, kw))

            if filterList:
                where_clause += ' AND (' + ' OR '.join(filterList) + ')'

        knowledge_tags = None
        custom_tags = None
        if 'tags' in request.GET:
            videotags_raw = request.GET['tags']
            tags_dict = json.loads(videotags_raw)

            authorid = tags_dict.get('authorid') or 0

            # authorid id values:
            #  0 not specified, all
            # -1 mgr only
            # -2 teacher only
            # otherwise: specific user
            # authorid: 对应管理员搜题时创建者的选项
            authorflt = ' AND authortype=%s ' % -authorid if authorid < 0 else ' AND authorid=%s ' % authorid
            if authorid:
                where_clause += authorflt

            lesson_type = tags_dict.get('lessontype',0)
            if lesson_type:
                where_clause += ' AND lessontype=%s ' % lesson_type

            for key, value in list(tags_dict.items()):
                if key == 'knowledgetreeidvalue':
                    knowledge_tags = KnowledgeTagRel.parse_tags(value, expect_long=False)
                elif key == 'customtags':
                    custom_tags = [CustomTagRel.parse_tags(v, expect_long=False) for v in value if v]

        if 'sgttags' in request.GET:
            inner_join_clause = ' INNER JOIN yj_sgt_tag_rel ON %s.id=yj_sgt_tag_rel.rel_id AND yj_sgt_tag_rel.rel_typeid=%s '%\
                              (Lesson._meta.db_table, SgtTagRel.TAG_TYPE_NAME2ID[Lesson.__name__])
            sgttags_raw = request.GET['sgttags']
            sgt_dict = json.loads(sgttags_raw)

            where_clause += ' AND ('
            #bugfix: textbookid
            where_clause += ') AND ('.join([' OR '.join(['yj_sgt_tag_rel.%s=%s'%(k,e) for e in SgtTagRel.toList(v)])
                                        for k,v in list(sgt_dict.items()) if v and k != 'textbookunitid' and k != 'textbookid'])
            where_clause += ') '

            if 'textbookunitid' in sgt_dict and sgt_dict['textbookunitid']:
                sgt_ags = SgtTagRel.parse_tags(sgt_dict['textbookunitid'], False)
                where_clause += ' AND ('
                # where_clause += ' OR '.join(['yj_sgt_tag_rel.textbookunitid LIKE \'%s%%\'' % tag for tag in sgt_ags])
                where_clause += ' OR '.join(["yj_sgt_tag_rel.textbookunitid='%s' OR yj_sgt_tag_rel.textbookunitid LIKE '%s\_%%'" % (tag,tag) for tag in sgt_ags])
                where_clause += ') '

        else:
            # no sgt tag chosen, left outer join
            inner_join_clause = ' LEFT OUTER JOIN yj_sgt_tag_rel ON %s.id=yj_sgt_tag_rel.rel_id AND yj_sgt_tag_rel.rel_typeid=%s '% \
                                (Lesson._meta.db_table, SgtTagRel.TAG_TYPE_NAME2ID[Lesson.__name__])
        if not needsgt:
            raw_sql = '''SELECT DISTINCT yj_lesson.id, yj_lesson.name,
                            yj_lesson.desc,yj_lesson.authortype, 0, yj_sgt_tag_rel.isdefault,  DATE_FORMAT(yj_lesson.create_time, '%Y-%m-%d %H:%i:%S') FROM yj_lesson'''
        else:
            raw_sql = '''SELECT DISTINCT yj_lesson.id, yj_lesson.name,
                            yj_lesson.desc,yj_lesson.authortype, yj_sgt_tag_rel.textbookunitid, yj_sgt_tag_rel.isdefault, DATE_FORMAT(yj_lesson.create_time, '%Y-%m-%d %H:%i:%S') FROM yj_lesson'''

        raw_sql += inner_join_clause

        if knowledge_tags:
            raw_sql += ' INNER JOIN yj_knowledgetags_rel on %s.id=yj_knowledgetags_rel.rel_id and yj_knowledgetags_rel.rel_typeid=%s ' % ('yj_lesson',KnowledgeTagRel.TAG_TYPE_NAME2ID[Lesson.__name__])
            where_clause += ' AND ('
            # where_clause += ' OR '.join(['yj_knowledgetags_rel.knowledgetag LIKE \'%s%%\'' % tag for tag in knowledge_tags])
            where_clause += ' OR '.join(["yj_knowledgetags_rel.knowledgetag='%s' OR yj_knowledgetags_rel.knowledgetag LIKE '%s\_%%'" % (tag,tag) for tag in knowledge_tags])
            where_clause += ') '

        if custom_tags:
            for idx, cutags in enumerate(custom_tags):
                raw_sql += ' INNER JOIN yj_custom_tag_rel as t%s on %s.id=t%s.rel_id and t%s.rel_typeid=%s ' % \
                           (idx, Lesson._meta.db_table, idx, idx, CustomTagRel.TAG_TYPE_NAME2ID[Lesson.__name__])
                where_clause += ' AND ('
                where_clause += ' OR '.join(['t%s.tag LIKE \'%s%%\'' % (idx,tag) for tag in cutags])
                where_clause += ') '

        raw_sql += ' WHERE %s' % where_clause

        if firstid == lastid and (firstid == -1 or firstid == '-1'):
            raw_sql += ' ORDER BY %s.id %s' % (
                Lesson._meta.db_table, orderby)
        else:
            raw_sql += ' ORDER BY %s.id %s LIMIT 10' % (
                Lesson._meta.db_table, orderby)

        if self.app_logger.level <= 10:  # debug level
            self.app_logger.debug("raw_sql:%s" % raw_sql)

        # generate count sql from raw sql
        count_sql = re.sub('SELECT DISTINCT (?:.|\n)+ FROM ', 'select count(distinct yj_lesson.id) from ',
                          raw_sql, flags=re.IGNORECASE)
        count_sql = count_sql.replace(' LIMIT 10', '')
        cursor = connection.cursor()

        cursor.execute(count_sql)
        nolimit = cursor.fetchall()

        count_sql = re.sub(' AND yj_lesson.id (?:>|<) \d+ ', ' ', count_sql, flags=re.IGNORECASE)

        cursor.execute(count_sql)
        total_count = cursor.fetchall()

        cursor.execute(raw_sql)
        rows = cursor.fetchall()

        result = {
            'retcode': 0,
            'retlist': rows,
            'total': total_count[0][0],
            'nolimit': nolimit[0][0]
        }

        cursor.close()

        return HttpResponse(json.dumps(result), content_type='application/json')


    def handle_mgr_add(self, request):

        self.checkMandatoryParams(request,['name', 'subjectid', 'lessontype'])
        self.is_int_params(request, ['authortype', 'lessontype', 'subjectid', 'quiztype'])
        self.param_in_options(request, 'lessontype', ['1', '3'])
        self.is_json_params(request, ['tags', 'sgttaglist', 'customsgttagsummary'])

        lessontype = int(request.param_dict['lessontype'])

        retObj = mm_Lesson.addOneLesson(request, mm_Lesson.AUTHORTYPE_ADMIN, lessontype)
        return JsonResponse(retObj)


    def handle_get_one(self, request, resource_id):

        if self.app_logger.level <= 10:
            self.app_logger.debug(
                "handle_get_one, resource id : {}.".format(resource_id))

        retObj = mm_Lesson.getOneLesson(resource_id)
        #retObj['retcode'] = 0
        return JsonResponse(retObj)

    def handle_setasdefaults(self, request):
        # validate parameters
        # tag, rel_id, rel_typeid, ext
        keys = ['sgt_lesson_defaults']
        pd = request.param_dict
        for key in keys:
            if key not in pd:
                return JsonResponse({'retcode': 1,'msg':'无效的参数'})

        # sgt_lesson_defaults: {tag: rel_id}
        for k,v in list(json.loads(pd[keys[0]]).items()):
            # clear all
            SgtTagRel.objects.filter(rel_typeid=SgtTagRel.TAG_TYPE_NAME2ID[Lesson.__name__],
                                     textbookunitid=k).update(isdefault=0)
            # set current as default
            SgtTagRel.objects.filter(rel_typeid=SgtTagRel.TAG_TYPE_NAME2ID[Lesson.__name__],
                                     rel_id=v,textbookunitid=k).update(isdefault=1)

        return JsonResponse({'retcode': 0})

    def handle_modify(self, request, resource_id):

        self.is_int_params(request, ['subjectid', 'lessontype'])
        self.is_json_params(request, ['questions', 'tags', 'sgttaglist', 'customsgttagsummary'])

        if hasattr(request.user, 'teacher'):  # 是老师
            check_user = True
        else:
            check_user = False

        retObj = mm_Lesson.modifyOneLesson(request.param_dict, resource_id, request.user.id, check_user)

        return JsonResponse(retObj)

    def handle_delete(self, request, resource_id):
        self.app_logger.debug("handle_delete, resource id: {}".format(resource_id))

        if mm_Task.filter(deliver_id=request.user.id, tasktype=2, relatedresourceid=resource_id).exists():
            return JsonResponse({'retcode': 1, 'msg': '该课已经发布在任务中，不能删除！！'})

        if hasattr(request.user, 'teacher'):  # 是老师
            check_user = True
        else:
            check_user = False

        parmDict = request.param_dict
        retObj = mm_Lesson.deleteOneLesson(parmDict, resource_id, request.user.id, check_user)
        if retObj['retcode'] == 0:
            mm_DailyRecord.delete_daily_record(mm_Lesson.model, [resource_id])

        return JsonResponse(retObj)

    def m_handle_search_base(self, request, author_limit=None):

        self.checkMandatoryParams(request,['lastid'])
        #subject = mm_Teacher.m_get_teacher_subject(request.user.teacher.id)
        if 'subject' in request.session and request.session['subject']:
            subjectid = request.session['subject']['subject_id']
        else:
            return JsonResponse({'retcode':1,'msg':'not subject for teacher with uid %s' % request.user.id})
        lastid = int(request.GET['lastid'])
        numlimit = int(request.GET['numlimit']) if 'numlimit' in request.GET else 20

        self.app_logger.debug("m_handle_search")

        # TODO to see if there is a better way to avoid to use
        # Lessons._meta.db_table, which is a protected method
        where_clause = ' %s.subjectid = %s' % (Lesson._meta.db_table, subjectid)

        if lastid > 0:
            where_clause += ' AND %s.id < %s' % (Lesson._meta.db_table, lastid)

        if author_limit:
            limitClause = []
            for oneLimit in author_limit:
                limitClause.append('(%s.authortype=%s and %s.authorid=%s)'% (Lesson._meta.db_table,
                                                                         oneLimit[0],
                                                                         Lesson._meta.db_table,
                                                                         oneLimit[1]))
            limitClauseStr = ' or '.join(limitClause)
            where_clause += ' AND ( ' + limitClauseStr + ' )'

        if 'sharedstatus' in request.GET:
            self.is_int_params(request, ['sharedstatus'])
            sharedstatus = request.GET.get('sharedstatus')
            limitClauseStr = '%s.sharedstatus="%s"' % (
                Lesson._meta.db_table, sharedstatus)
            where_clause += ' AND ( ' + limitClauseStr + ' )'

        if 'createtimebefore' in request.GET:
            createtime_string = time.strftime(
                "%Y-%m-%d %H:%M:%S", time.gmtime(
                    float(request.GET['createtimebefore'])))
            limitClauseStr = '%s.create_time<="%s"' % (
                Lesson._meta.db_table, createtime_string)
            where_clause += ' AND ( ' + limitClauseStr + ' )'

        if 'createtimeafter' in request.GET:
            createtime_string = time.strftime(
                "%Y-%m-%d %H:%M:%S", time.gmtime(
                    float(request.GET['createtimeafter'])))
            limitClauseStr = '%s.create_time>="%s"' % (
                Lesson._meta.db_table, createtime_string)
            where_clause += ' AND ( ' + limitClauseStr + ' )'

        if 'searchkeyword' in request.GET:
            filterList = []
            kwStr = request.GET['searchkeyword']
            kwList = kwStr.split(' ')

            for kw in kwList:
                if kw:
                    filterList.append(
                        "%s.name LIKE BINARY '%%%s%%' " % (
                            Lesson._meta.db_table, kw))

            if filterList:
                where_clause += ' AND (' + ' OR '.join(filterList) + ')'

        knowledge_tags = None
        custom_tags = None
        if 'tags' in request.GET:
            videotags_raw = request.GET['tags']
            tags_dict = json.loads(videotags_raw)

            for key, value in list(tags_dict.items()):
                if key == 'knowledgetreeidvalue':
                    knowledge_tags = KnowledgeTagRel.parse_tags(value, expect_long=False)
                elif key == 'customtags':
                    custom_tags = [CustomTagRel.parse_tags(v, expect_long=False) for v in value if v]

        if 'sgt_dict' in request.GET:
            inner_join_clause = ' INNER JOIN yj_sgt_tag_rel ON %s.id=yj_sgt_tag_rel.rel_id AND yj_sgt_tag_rel.rel_typeid=%s '%\
                              (Lesson._meta.db_table, SgtTagRel.TAG_TYPE_NAME2ID[Lesson.__name__])
            sgttags_raw = request.GET['sgt_dict']
            sgt_dict = json.loads(sgttags_raw)

            where_clause += ' AND ('
            #bugfix: textbookid
            where_clause += ') AND ('.join([' OR '.join(['yj_sgt_tag_rel.%s=%s'%(k,e) for e in SgtTagRel.toList(v)])
                                        for k,v in list(sgt_dict.items()) if v and k != 'textbookunitid' and k != 'textbookid'])
            where_clause += ') '

            if 'textbookunitid' in sgt_dict and sgt_dict['textbookunitid']:
                sgt_ags = SgtTagRel.parse_tags(sgt_dict['textbookunitid'], False)
                where_clause += ' AND ('
                # where_clause += ' OR '.join(['yj_sgt_tag_rel.textbookunitid LIKE \'%s%%\'' % tag for tag in sgt_ags])
                where_clause += ' OR '.join(["yj_sgt_tag_rel.textbookunitid='%s' OR yj_sgt_tag_rel.textbookunitid LIKE '%s\_%%'" % (tag,tag) for tag in sgt_ags])
                where_clause += ') '
            raw_sql = '''SELECT DISTINCT yj_lesson.id, yj_lesson.name,
                        yj_lesson.desc,yj_lesson.authortype, yj_sgt_tag_rel.textbookunitid, yj_sgt_tag_rel.isdefault,yj_lesson.create_time, yj_lesson.sharedstatus, yj_lesson.verifydesc FROM yj_lesson'''


        else:
            # no sgt tag chosen, left outer join
            inner_join_clause = ' LEFT OUTER JOIN yj_sgt_tag_rel ON %s.id=yj_sgt_tag_rel.rel_id AND yj_sgt_tag_rel.rel_typeid=%s '% \
                                (Lesson._meta.db_table, SgtTagRel.TAG_TYPE_NAME2ID[Lesson.__name__])
            raw_sql = '''SELECT DISTINCT yj_lesson.id, yj_lesson.name,
                        yj_lesson.desc,yj_lesson.authortype, 0, yj_sgt_tag_rel.isdefault,yj_lesson.create_time, yj_lesson.sharedstatus, yj_lesson.verifydesc FROM yj_lesson'''

        raw_sql += inner_join_clause

        if knowledge_tags:
            raw_sql += ' INNER JOIN yj_knowledgetags_rel on %s.id=yj_knowledgetags_rel.rel_id and yj_knowledgetags_rel.rel_typeid=%s ' % ('yj_lesson',KnowledgeTagRel.TAG_TYPE_NAME2ID[Lesson.__name__])
            where_clause += ' AND ('
            # where_clause += ' OR '.join(['yj_knowledgetags_rel.knowledgetag LIKE \'%s%%\'' % tag for tag in knowledge_tags])
            where_clause += ' OR '.join(["yj_knowledgetags_rel.knowledgetag='%s' OR yj_knowledgetags_rel.knowledgetag LIKE '%s\_%%'" % (tag,tag) for tag in knowledge_tags])
            where_clause += ') '

        if custom_tags:
            for idx, cutags in enumerate(custom_tags):
                raw_sql += ' INNER JOIN yj_custom_tag_rel as t%s on %s.id=t%s.rel_id and t%s.rel_typeid=%s ' % \
                           (idx, Lesson._meta.db_table, idx, idx, CustomTagRel.TAG_TYPE_NAME2ID[Lesson.__name__])
                where_clause += ' AND ('
                where_clause += ' OR '.join(['t%s.tag LIKE \'%s%%\'' % (idx,tag) for tag in cutags])
                where_clause += ') '

        raw_sql += ' WHERE %s' % where_clause

        raw_sql += ' ORDER BY %s.id DESC LIMIT %s' % (
                Lesson._meta.db_table, numlimit)

        if self.app_logger.level <= 10:  # debug level
            self.app_logger.debug("raw_sql:%s" % raw_sql)

        cursor = connection.cursor()

        cursor.execute(raw_sql)
        rows = cursor.fetchall()

        result = {
            'retcode': 0,
            'retlist': rows
        }

        cursor.close()

        #return HttpResponse(json.dumps(result), content_type='application/json')
        return JsonResponse(result)

    def m_handle_modify(self, request):
        """
        :param request:
        :return:
           "questionList":[["choice",[{"id":1598,"level":3},{"id":1599,"level":3},{"id":1596,"level":3}]],[]]}
        """
        self.checkMandatoryParams(request, ['id'])
        self.is_int_params(request, ['subjectid', 'lessontype'])
        self.is_json_params(request, ['questions', 'tags', 'sgttaglist', 'customsgttagsummary'])
        param_dict = deepcopy(request.param_dict)

        if hasattr(request.user, 'teacher'):  # 是老师
            check_user = True
            param_dict['subjectid'] = request.session['subject']['subject_id']
        else:
            check_user = False

        if 'questions' in param_dict:
            questions = json.loads(param_dict['questions'])
            param_dict['quizcontent'] = json.dumps({"type": 1, "rule": 5, "questionList": questions})
        param_dict['quiztype'] = 1
        retObj = mm_Lesson.modifyOneLesson(param_dict, request.param_dict['id'], request.user.id, check_user)

        return JsonResponse(retObj)

    def handle_get_kp_lessons(self,request):
        self.checkMandatoryParams(request,['kpid'])
        return JsonResponse({'retcode':0,'data':{'lessons':mm_Lesson.getKPLessonsByKnowledgeTag(request.param_dict['kpid'])}})

    def set_lesson_shared_status(self, request):
        self.checkMandatoryParams(request, ['id', 'sharedstatus'])
        self.is_int_params(request, ['id'])
        self.param_in_options(request, 'sharedstatus', ['0', '1', '2', '3'])

        user_id = request.user.id
        user_type = request.session['ut']
        lesson_id = int(request.param_dict['id'])
        sharedstatus = int(request.param_dict['sharedstatus'])
        resp = mm_Lesson.set_lesson_shared_status(lesson_id, sharedstatus, user_id, user_type)

        return JsonResponse(resp)

    def add_shared_lesson_watchcount(self, request):
        self.checkMandatoryParams(request, ['id'])
        self.is_int_params(request, ['id'])

        lesson_id = request.param_dict['id']
        lesson = mm_Lesson.get_or_default(
            id=lesson_id,
            authortype=mm_Lesson.AUTHORTYPE_TEACHER,
            sharedstatus=mm_Lesson.LESSON_SHARED_SUCCESS,
            is_raise=True,
        )
        subjectid = lesson.subjectid
        mm_DailyRecord.set_daily_record(lesson, subject_id=subjectid)
        resp = mm_Lesson.add_lesson_watch_count(lesson_id, lesson)

        return JsonResponse(resp)

    def get_max_watchcount_shared_lesson(self, request):
        self.is_int_params(request, ['max_num', 'subject_id'])
        self.param_in_options(request, 'order_type', ['teacher', 'lesson'])

        order_type = request.param_dict.get('order_type', 'teacher')
        max_num = int(request.param_dict.get('max_num', 3))
        subject_id = request.param_dict.get('subject_id')
        from_date = datetime.date(datetime.date.today().year,
                                  datetime.date.today().month,
                                  1)
        end_date = datetime.datetime.now()

        lesson_para = {
            'dataObj': mm_Lesson.model,
            'from_date': from_date,
            'end_date': end_date,
            'action_type': 1,
        }

        if hasattr(request.user, 'teacher'):
            subject_id = request.session['subject']['subject_id']
        if subject_id:
            lesson_para['subject_ids'] = [int(subject_id)]
        lessons = mm_DailyRecord.get_daily_record_sort(**lesson_para)
        if not lessons:
            lesson_para['from_date'] = datetime.datetime.min
            lessons = mm_DailyRecord.get_daily_record_sort(**lesson_para)

        lesson_ids = [l[0] for l in lessons]
        at = mm_Lesson.AUTHORTYPE_TEACHER
        lesson_infos = mm_Lesson.lesson_info_by_ids(lesson_ids, at)

        authorids = [l['authorid'] for l in list(lesson_infos.values())]
        teacher_infos = mm_Teacher.teacher_info_by_uids(authorids)

        school_ids = [t['schoolid'] for t in list(teacher_infos.values())]
        school_infos = mm_School.school_ids_to_school_names(school_ids)

        subject_table = mm_SubjectAvatar.model.list(useCache=True)['rettable']

        teachers = []
        if order_type == 'lesson':
            for lesson_id, watch_count in lessons:
                if len(teachers) >= max_num:
                    break
                subject_id = lesson_infos.get('lesson_id', {}).get('subjectid')
                if not subject_id:
                    continue
                user_id = lesson_infos[lesson_id]['authorid']
                school_id = teacher_infos[user_id]['schoolid']
                teachers.append({
                    'subject_id': subject_id,
                    'subject_name': subject_table[subject_id]['name'][-2:],
                    'lesson_id': lesson_id,
                    'watch_count': watch_count,
                    'user_id': user_id,
                    'realname': teacher_infos[user_id]['realname'],
                    'avatar_url': teacher_infos[user_id]['avatar_url'],
                    'schoolname': school_infos[school_id]
                })

        if order_type == 'teacher':
            teacheruid_to_watchcount = defaultdict(int)
            for lesson_id, watch_count in lessons:
                user_id = lesson_infos[lesson_id]['authorid']
                teacheruid_to_watchcount[user_id] += watch_count
            teacher_orders = sorted(iter(teacheruid_to_watchcount.items()),
                                    key=lambda l: l[1], reverse=True)

            for user_id, watch_count in teacher_orders:
                if len(teachers) >= max_num:
                    break
                subject_id = teacher_infos[user_id]['subject_id']
                if not subject_id:
                    continue
                school_id = teacher_infos[user_id]['schoolid']
                teachers.append({
                    'subject_id': subject_id,
                    'subject_name': subject_table[subject_id]['name'][-2:],
                    'watch_count': watch_count,
                    'user_id': user_id,
                    'realname': teacher_infos[user_id]['realname'],
                    'avatar_url': teacher_infos[user_id]['avatar_url'],
                    'schoolname': school_infos[school_id]
                })

        return JsonResponse({
            'retcode': 0,
            'teachers': teachers,
        })

    def get_lesson_comments(self, request):
        self.checkMandatoryParams(request, ['resource_id', 'page'])
        self.is_int_params(request, ['resource_id', 'page'])
        resource_id = request.param_dict.get('resource_id')
        page = int(request.param_dict.get('page'))
        try:
            lesson = Lesson.objects.get(id=resource_id)
        except Lesson.DoesNotExist:
            return JsonResponse({
                'retcode': 404,
                'msg': 'id 为`{}`的亿教课不存在'.format(resource_id),
            })

        retObj = mm_Comment.get_comment(request.user, lesson, page)

        dt = mm_Thumb.dict_tree()
        for thumb in mm_Thumb.user_thumb_list(request.user.id, 0):
            dt[thumb['rel_id']][thumb['index_id']] = 1
        for ds in retObj['data']:
            ds['thumb_self'] = int(bool(dt[ds['comment_id']][0]))
            for d in ds['reply_data']:
                d['thumb_self'] = int(bool(dt[ds['comment_id']][d['reply_id']]))

        for ds in retObj['hot_data']:
            ds['thumb_self'] = int(bool(dt[ds['comment_id']][0]))
            for d in ds['reply_data']:
                d['thumb_self'] = int(bool(dt[ds['comment_id']][d['reply_id']]))

        return JsonResponse(retObj)

    def get_lesson_replys(self, request):
        self.checkMandatoryParams(request, ['comment_id', 'page'])
        self.is_int_params(request, ['comment_id', 'page'])
        comment_id = request.param_dict.get('comment_id')
        page = int(request.param_dict.get('page'))
        return JsonResponse(mm_Comment.get_comment_for_reply(comment_id, request.user, page))

    def set_lesson_comments(self, request):
        self.checkMandatoryParams(request, ['content', 'id'])
        ip_address = request.META.get('REMOTE_ADDR')
        try:
            content_type, id = request.param_dict.get('id').split('_')
        except Exception as e:
            return JsonResponse({'retcode': 1, 'msg': '名为id的参数错误，正确格式为例：resource_13'})
        user = request.user
        userType = request.session['ut']
        if content_type == 'resource':
            try:
                lesson = Lesson.objects.get(id=id)
            except Exception as e:
                return {'retcode': 404,
                     'msg': 'id 为`{}`的亿教课不存在'.format(id)}
            retObj = mm_Comment.set_comment_main(user, request.param_dict, ip_address, userType, lesson)
        else:
            retObj = mm_Comment.set_comment_main(user, request.param_dict, ip_address, userType)
        return JsonResponse(retObj)

    def modify_comment(self, request):
        self.checkMandatoryParams(request, ['tag'])
        ut = int(request.session.get('ut'))
        user = request.user
        return JsonResponse(mm_Comment.modify_comment_main(user, request.param_dict, ut))

    def handle_preview(self, request):
        """
        查看某微课的详情
        :param request:
        :return:
        """
        self.checkMandatoryParams(request, ['id'])
        self.is_not_zero_int_params(request, ['id'])

        resp = mm_Lesson.getOneLessonAndAllQuestions(request.param_dict['id'], is_raise=True)

        if request.session['ut'] == USER_TYPE.STDUENT:
            user_id = request.user.id
            subject_id = resp['lessonobj']['subjectid']
            resp.update(mm_ProductPurchase.is_user_member_of_subject(user_id, subject_id))

        elif request.session['ut'] == USER_TYPE.PARENTS:
            user_id = request.user.id
            subject_id = resp['lessonobj']['subjectid']
            student_uids = mm_ParentStudentRelation.filter(parent__user_id=user_id).values_list('child__user_id', flat=True)
            couldview = 0
            couldtry = 0
            for uid in student_uids:
                is_member = mm_ProductPurchase.is_user_member_of_subject(uid, subject_id)
                if is_member['retcode'] == 0:
                    if is_member['couldview']:
                        couldview = 1
                        break
                    elif is_member['couldtry']:
                        couldtry = 1
            couldtry = 0 if couldview else couldtry
            resp['couldview'] = couldview
            resp['couldtry'] = couldtry

        return JsonResponse(resp)
